﻿// A Force-Directed Diagram Layout Algorithm
// Bradley Smith - 2010/07/01

// uncomment the following line to animate the iterations of the force-directed algorithm:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.Text;

namespace ForceDirected {

	public partial class Demo : Form {

		private Diagram mDiagram;
        private Random mRandom;
        private System.Timers.Timer drawTimer;
        private UdpClient client;
        private IPEndPoint endpoint = null;

		public Demo() {
            try
            {
                endpoint = new IPEndPoint(IPAddress.Parse("255.255.255.255"), 1984);
                InitializeComponent();
                mDiagram = new Diagram();
                mRandom = new Random();
                drawTimer = new System.Timers.Timer();
                drawTimer.Elapsed += new System.Timers.ElapsedEventHandler(drawTimer_Elapsed);
                drawTimer.Interval = 5000;
                drawTimer.Start();
                client = new UdpClient(endpoint);
                var thread = new Thread(new ThreadStart(receiveThread));
                thread.IsBackground = true;
                thread.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Exception:" + ex.Message);
                Environment.Exit(-1);
            }
		}

        protected void receiveThread()
        {
            ASCIIEncoding enc = new ASCIIEncoding();
            while (true)
            {
                try
                {
                    byte[] bytes = client.Receive(ref endpoint);
                    string s = enc.GetString(bytes);
                    string[] ss = s.Split(',');
                    string peer1 = ss[0];
                    string peer2 = ss[1];

                    SpotNode node1 = null;
                    SpotNode node2 = null;

                    foreach (SpotNode node in mDiagram.Nodes)
                    {
                        if (node.mName.Equals(peer1))
                        {
                            node1 = node;
                        }
                        if (node.mName.Equals(peer2))
                        {
                            node2 = node;
                        }
                    }

                    if (node1 == null)
                    {
                        node1 = new SpotNode(Color.Black, peer1);
                        mDiagram.AddNode(node1);
                    }
                    if (node2 == null)
                    {
                        node2 = new SpotNode(Color.Black, peer2);
                        mDiagram.AddNode(node2);
                    }

                    if (ss.Length == 3 && ss[2].Equals("Remove"))
                    {
                       foreach(SpotNode node in node1.Connections){
                           if(node.mName.Equals(node2.mName)){
                               node1.RemoveChild(node2);
                           }
                       }
                    }
                    else
                    {
                        node1.AddChild(node2);
                    }
                    
                    mDiagram.Sort();

                }
                catch (Exception ex)
                {
                    //wtf?
                }                
            }
        }

		protected override void OnPaint(PaintEventArgs e) {
			base.OnPaint(e);

            try
            {
                // draw with anti-aliasing and a 12 pixel border
                e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                mDiagram.Draw(e.Graphics, Rectangle.FromLTRB(12, 12, ClientSize.Width - 12, ClientSize.Height - 12));
            }
            catch (Exception ex)
            {
                //wtf ?
            }
		}

		protected override void OnResize(EventArgs e) {
			base.OnResize(e);

			// redraw on resize
			Invalidate();
		}

        public void drawTimer_Elapsed(object sender, EventArgs args)
        {
            try
            {
                // run the force-directed algorithm (async)
                mDiagram.Arrange();                  
                Invalidate();
            }
            catch (Exception ex)
            {
                //wtf?
            }
		}
	}
}
